use std::fmt;
use std::str::FromStr;

/// SAI object type
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u32)]
pub enum SaiObjectType {
    /// invalid object type
    Null = 0,
    Port = 1,
    Lag = 2,
    VirtualRouter = 3,
    NextHop = 4,
    NextHopGroup = 5,
    RouterInterface = 6,
    AclTable = 7,
    AclEntry = 8,
    AclCounter = 9,
    AclRange = 10,
    AclTableGroup = 11,
    AclTableGroupMember = 12,
    Hostif = 13,
    MirrorSession = 14,
    Samplepacket = 15,
    Stp = 16,
    HostifTrapGroup = 17,
    Policer = 18,
    Wred = 19,
    QosMap = 20,
    Queue = 21,
    Scheduler = 22,
    SchedulerGroup = 23,
    BufferPool = 24,
    BufferProfile = 25,
    IngressPriorityGroup = 26,
    LagMember = 27,
    Hash = 28,
    Udf = 29,
    UdfMatch = 30,
    UdfGroup = 31,
    FdbEntry = 32,
    Switch = 33,
    HostifTrap = 34,
    HostifTableEntry = 35,
    NeighborEntry = 36,
    RouteEntry = 37,
    Vlan = 38,
    VlanMember = 39,
    HostifPacket = 40,
    TunnelMap = 41,
    Tunnel = 42,
    TunnelTermTableEntry = 43,
    FdbFlush = 44,
    NextHopGroupMember = 45,
    StpPort = 46,
    RpfGroup = 47,
    RpfGroupMember = 48,
    L2mcGroup = 49,
    L2mcGroupMember = 50,
    IpmcGroup = 51,
    IpmcGroupMember = 52,
    L2mcEntry = 53,
    IpmcEntry = 54,
    McastFdbEntry = 55,
    HostifUserDefinedTrap = 56,
    Bridge = 57,
    BridgePort = 58,
    TunnelMapEntry = 59,
    Tam = 60,
    Srv6Sidlist = 61,
    PortPool = 62,
    InsegEntry = 63,
    /// experimental
    Dtel = 64,
    /// experimental
    DtelQueueReport = 65,
    /// experimental
    DtelIntSession = 66,
    /// experimental
    DtelReportSession = 67,
    /// experimental
    DtelEvent = 68,
    BfdSession = 69,
    IsolationGroup = 70,
    IsolationGroupMember = 71,
    TamMathFunc = 72,
    TamReport = 73,
    TamEventThreshold = 74,
    TamTelType = 75,
    TamTransport = 76,
    TamTelemetry = 77,
    TamCollector = 78,
    TamEventAction = 79,
    TamEvent = 80,
    NatZoneCounter = 81,
    NatEntry = 82,
    TamInt = 83,
    Counter = 84,
    DebugCounter = 85,
    PortConnector = 86,
    PortSerdes = 87,
    Macsec = 88,
    MacsecPort = 89,
    MacsecFlow = 90,
    MacsecSc = 91,
    MacsecSa = 92,
    SystemPort = 93,
    FineGrainedHashField = 94,
    SwitchTunnel = 95,
    MySidEntry = 96,
    MyMac = 97,
    NextHopGroupMap = 98,
    Ipsec = 99,
    IpsecPort = 100,
    IpsecSa = 101,
    GenericProgrammable = 102,
    ArsProfile = 103,
    Ars = 104,
    AclTableChainGroup = 105,
    TwampSession = 106,
    TamCounterSubscription = 107,
    PoeDevice = 108,
    PoePse = 109,
    PoePort = 110,
    IcmpEchoSession = 111,
    PrefixCompressionTable = 112,
    PrefixCompressionEntry = 113,
    SynceClock = 114,
    /// Must remain in last position
    Max = 115,
    /// Custom range base
    CustomRangeBase = 0x10000000,
    ExtensionsRangeBase = 0x20000000,
}

impl SaiObjectType {
    /// Convert from u32 to SaiObjectType
    pub fn from_u32(value: u32) -> Option<Self> {
        match value {
            0 => Some(Self::Null),
            1 => Some(Self::Port),
            2 => Some(Self::Lag),
            3 => Some(Self::VirtualRouter),
            4 => Some(Self::NextHop),
            5 => Some(Self::NextHopGroup),
            6 => Some(Self::RouterInterface),
            7 => Some(Self::AclTable),
            8 => Some(Self::AclEntry),
            9 => Some(Self::AclCounter),
            10 => Some(Self::AclRange),
            11 => Some(Self::AclTableGroup),
            12 => Some(Self::AclTableGroupMember),
            13 => Some(Self::Hostif),
            14 => Some(Self::MirrorSession),
            15 => Some(Self::Samplepacket),
            16 => Some(Self::Stp),
            17 => Some(Self::HostifTrapGroup),
            18 => Some(Self::Policer),
            19 => Some(Self::Wred),
            20 => Some(Self::QosMap),
            21 => Some(Self::Queue),
            22 => Some(Self::Scheduler),
            23 => Some(Self::SchedulerGroup),
            24 => Some(Self::BufferPool),
            25 => Some(Self::BufferProfile),
            26 => Some(Self::IngressPriorityGroup),
            27 => Some(Self::LagMember),
            28 => Some(Self::Hash),
            29 => Some(Self::Udf),
            30 => Some(Self::UdfMatch),
            31 => Some(Self::UdfGroup),
            32 => Some(Self::FdbEntry),
            33 => Some(Self::Switch),
            34 => Some(Self::HostifTrap),
            35 => Some(Self::HostifTableEntry),
            36 => Some(Self::NeighborEntry),
            37 => Some(Self::RouteEntry),
            38 => Some(Self::Vlan),
            39 => Some(Self::VlanMember),
            40 => Some(Self::HostifPacket),
            41 => Some(Self::TunnelMap),
            42 => Some(Self::Tunnel),
            43 => Some(Self::TunnelTermTableEntry),
            44 => Some(Self::FdbFlush),
            45 => Some(Self::NextHopGroupMember),
            46 => Some(Self::StpPort),
            47 => Some(Self::RpfGroup),
            48 => Some(Self::RpfGroupMember),
            49 => Some(Self::L2mcGroup),
            50 => Some(Self::L2mcGroupMember),
            51 => Some(Self::IpmcGroup),
            52 => Some(Self::IpmcGroupMember),
            53 => Some(Self::L2mcEntry),
            54 => Some(Self::IpmcEntry),
            55 => Some(Self::McastFdbEntry),
            56 => Some(Self::HostifUserDefinedTrap),
            57 => Some(Self::Bridge),
            58 => Some(Self::BridgePort),
            59 => Some(Self::TunnelMapEntry),
            60 => Some(Self::Tam),
            61 => Some(Self::Srv6Sidlist),
            62 => Some(Self::PortPool),
            63 => Some(Self::InsegEntry),
            64 => Some(Self::Dtel),
            65 => Some(Self::DtelQueueReport),
            66 => Some(Self::DtelIntSession),
            67 => Some(Self::DtelReportSession),
            68 => Some(Self::DtelEvent),
            69 => Some(Self::BfdSession),
            70 => Some(Self::IsolationGroup),
            71 => Some(Self::IsolationGroupMember),
            72 => Some(Self::TamMathFunc),
            73 => Some(Self::TamReport),
            74 => Some(Self::TamEventThreshold),
            75 => Some(Self::TamTelType),
            76 => Some(Self::TamTransport),
            77 => Some(Self::TamTelemetry),
            78 => Some(Self::TamCollector),
            79 => Some(Self::TamEventAction),
            80 => Some(Self::TamEvent),
            81 => Some(Self::NatZoneCounter),
            82 => Some(Self::NatEntry),
            83 => Some(Self::TamInt),
            84 => Some(Self::Counter),
            85 => Some(Self::DebugCounter),
            86 => Some(Self::PortConnector),
            87 => Some(Self::PortSerdes),
            88 => Some(Self::Macsec),
            89 => Some(Self::MacsecPort),
            90 => Some(Self::MacsecFlow),
            91 => Some(Self::MacsecSc),
            92 => Some(Self::MacsecSa),
            93 => Some(Self::SystemPort),
            94 => Some(Self::FineGrainedHashField),
            95 => Some(Self::SwitchTunnel),
            96 => Some(Self::MySidEntry),
            97 => Some(Self::MyMac),
            98 => Some(Self::NextHopGroupMap),
            99 => Some(Self::Ipsec),
            100 => Some(Self::IpsecPort),
            101 => Some(Self::IpsecSa),
            102 => Some(Self::GenericProgrammable),
            103 => Some(Self::ArsProfile),
            104 => Some(Self::Ars),
            105 => Some(Self::AclTableChainGroup),
            106 => Some(Self::TwampSession),
            107 => Some(Self::TamCounterSubscription),
            108 => Some(Self::PoeDevice),
            109 => Some(Self::PoePse),
            110 => Some(Self::PoePort),
            111 => Some(Self::IcmpEchoSession),
            112 => Some(Self::PrefixCompressionTable),
            113 => Some(Self::PrefixCompressionEntry),
            114 => Some(Self::SynceClock),
            115 => Some(Self::Max),
            0x10000000 => Some(Self::CustomRangeBase),
            0x20000000 => Some(Self::ExtensionsRangeBase),
            _ => None,
        }
    }

    /// Convert to u32
    pub fn to_u32(self) -> u32 {
        self as u32
    }

    /// Get the string name (original C enum name)
    pub fn to_c_name(self) -> &'static str {
        match self {
            Self::Null => "SAI_OBJECT_TYPE_NULL",
            Self::Port => "SAI_OBJECT_TYPE_PORT",
            Self::Lag => "SAI_OBJECT_TYPE_LAG",
            Self::VirtualRouter => "SAI_OBJECT_TYPE_VIRTUAL_ROUTER",
            Self::NextHop => "SAI_OBJECT_TYPE_NEXT_HOP",
            Self::NextHopGroup => "SAI_OBJECT_TYPE_NEXT_HOP_GROUP",
            Self::RouterInterface => "SAI_OBJECT_TYPE_ROUTER_INTERFACE",
            Self::AclTable => "SAI_OBJECT_TYPE_ACL_TABLE",
            Self::AclEntry => "SAI_OBJECT_TYPE_ACL_ENTRY",
            Self::AclCounter => "SAI_OBJECT_TYPE_ACL_COUNTER",
            Self::AclRange => "SAI_OBJECT_TYPE_ACL_RANGE",
            Self::AclTableGroup => "SAI_OBJECT_TYPE_ACL_TABLE_GROUP",
            Self::AclTableGroupMember => "SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER",
            Self::Hostif => "SAI_OBJECT_TYPE_HOSTIF",
            Self::MirrorSession => "SAI_OBJECT_TYPE_MIRROR_SESSION",
            Self::Samplepacket => "SAI_OBJECT_TYPE_SAMPLEPACKET",
            Self::Stp => "SAI_OBJECT_TYPE_STP",
            Self::HostifTrapGroup => "SAI_OBJECT_TYPE_HOSTIF_TRAP_GROUP",
            Self::Policer => "SAI_OBJECT_TYPE_POLICER",
            Self::Wred => "SAI_OBJECT_TYPE_WRED",
            Self::QosMap => "SAI_OBJECT_TYPE_QOS_MAP",
            Self::Queue => "SAI_OBJECT_TYPE_QUEUE",
            Self::Scheduler => "SAI_OBJECT_TYPE_SCHEDULER",
            Self::SchedulerGroup => "SAI_OBJECT_TYPE_SCHEDULER_GROUP",
            Self::BufferPool => "SAI_OBJECT_TYPE_BUFFER_POOL",
            Self::BufferProfile => "SAI_OBJECT_TYPE_BUFFER_PROFILE",
            Self::IngressPriorityGroup => "SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP",
            Self::LagMember => "SAI_OBJECT_TYPE_LAG_MEMBER",
            Self::Hash => "SAI_OBJECT_TYPE_HASH",
            Self::Udf => "SAI_OBJECT_TYPE_UDF",
            Self::UdfMatch => "SAI_OBJECT_TYPE_UDF_MATCH",
            Self::UdfGroup => "SAI_OBJECT_TYPE_UDF_GROUP",
            Self::FdbEntry => "SAI_OBJECT_TYPE_FDB_ENTRY",
            Self::Switch => "SAI_OBJECT_TYPE_SWITCH",
            Self::HostifTrap => "SAI_OBJECT_TYPE_HOSTIF_TRAP",
            Self::HostifTableEntry => "SAI_OBJECT_TYPE_HOSTIF_TABLE_ENTRY",
            Self::NeighborEntry => "SAI_OBJECT_TYPE_NEIGHBOR_ENTRY",
            Self::RouteEntry => "SAI_OBJECT_TYPE_ROUTE_ENTRY",
            Self::Vlan => "SAI_OBJECT_TYPE_VLAN",
            Self::VlanMember => "SAI_OBJECT_TYPE_VLAN_MEMBER",
            Self::HostifPacket => "SAI_OBJECT_TYPE_HOSTIF_PACKET",
            Self::TunnelMap => "SAI_OBJECT_TYPE_TUNNEL_MAP",
            Self::Tunnel => "SAI_OBJECT_TYPE_TUNNEL",
            Self::TunnelTermTableEntry => "SAI_OBJECT_TYPE_TUNNEL_TERM_TABLE_ENTRY",
            Self::FdbFlush => "SAI_OBJECT_TYPE_FDB_FLUSH",
            Self::NextHopGroupMember => "SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER",
            Self::StpPort => "SAI_OBJECT_TYPE_STP_PORT",
            Self::RpfGroup => "SAI_OBJECT_TYPE_RPF_GROUP",
            Self::RpfGroupMember => "SAI_OBJECT_TYPE_RPF_GROUP_MEMBER",
            Self::L2mcGroup => "SAI_OBJECT_TYPE_L2MC_GROUP",
            Self::L2mcGroupMember => "SAI_OBJECT_TYPE_L2MC_GROUP_MEMBER",
            Self::IpmcGroup => "SAI_OBJECT_TYPE_IPMC_GROUP",
            Self::IpmcGroupMember => "SAI_OBJECT_TYPE_IPMC_GROUP_MEMBER",
            Self::L2mcEntry => "SAI_OBJECT_TYPE_L2MC_ENTRY",
            Self::IpmcEntry => "SAI_OBJECT_TYPE_IPMC_ENTRY",
            Self::McastFdbEntry => "SAI_OBJECT_TYPE_MCAST_FDB_ENTRY",
            Self::HostifUserDefinedTrap => "SAI_OBJECT_TYPE_HOSTIF_USER_DEFINED_TRAP",
            Self::Bridge => "SAI_OBJECT_TYPE_BRIDGE",
            Self::BridgePort => "SAI_OBJECT_TYPE_BRIDGE_PORT",
            Self::TunnelMapEntry => "SAI_OBJECT_TYPE_TUNNEL_MAP_ENTRY",
            Self::Tam => "SAI_OBJECT_TYPE_TAM",
            Self::Srv6Sidlist => "SAI_OBJECT_TYPE_SRV6_SIDLIST",
            Self::PortPool => "SAI_OBJECT_TYPE_PORT_POOL",
            Self::InsegEntry => "SAI_OBJECT_TYPE_INSEG_ENTRY",
            Self::Dtel => "SAI_OBJECT_TYPE_DTEL",
            Self::DtelQueueReport => "SAI_OBJECT_TYPE_DTEL_QUEUE_REPORT",
            Self::DtelIntSession => "SAI_OBJECT_TYPE_DTEL_INT_SESSION",
            Self::DtelReportSession => "SAI_OBJECT_TYPE_DTEL_REPORT_SESSION",
            Self::DtelEvent => "SAI_OBJECT_TYPE_DTEL_EVENT",
            Self::BfdSession => "SAI_OBJECT_TYPE_BFD_SESSION",
            Self::IsolationGroup => "SAI_OBJECT_TYPE_ISOLATION_GROUP",
            Self::IsolationGroupMember => "SAI_OBJECT_TYPE_ISOLATION_GROUP_MEMBER",
            Self::TamMathFunc => "SAI_OBJECT_TYPE_TAM_MATH_FUNC",
            Self::TamReport => "SAI_OBJECT_TYPE_TAM_REPORT",
            Self::TamEventThreshold => "SAI_OBJECT_TYPE_TAM_EVENT_THRESHOLD",
            Self::TamTelType => "SAI_OBJECT_TYPE_TAM_TEL_TYPE",
            Self::TamTransport => "SAI_OBJECT_TYPE_TAM_TRANSPORT",
            Self::TamTelemetry => "SAI_OBJECT_TYPE_TAM_TELEMETRY",
            Self::TamCollector => "SAI_OBJECT_TYPE_TAM_COLLECTOR",
            Self::TamEventAction => "SAI_OBJECT_TYPE_TAM_EVENT_ACTION",
            Self::TamEvent => "SAI_OBJECT_TYPE_TAM_EVENT",
            Self::NatZoneCounter => "SAI_OBJECT_TYPE_NAT_ZONE_COUNTER",
            Self::NatEntry => "SAI_OBJECT_TYPE_NAT_ENTRY",
            Self::TamInt => "SAI_OBJECT_TYPE_TAM_INT",
            Self::Counter => "SAI_OBJECT_TYPE_COUNTER",
            Self::DebugCounter => "SAI_OBJECT_TYPE_DEBUG_COUNTER",
            Self::PortConnector => "SAI_OBJECT_TYPE_PORT_CONNECTOR",
            Self::PortSerdes => "SAI_OBJECT_TYPE_PORT_SERDES",
            Self::Macsec => "SAI_OBJECT_TYPE_MACSEC",
            Self::MacsecPort => "SAI_OBJECT_TYPE_MACSEC_PORT",
            Self::MacsecFlow => "SAI_OBJECT_TYPE_MACSEC_FLOW",
            Self::MacsecSc => "SAI_OBJECT_TYPE_MACSEC_SC",
            Self::MacsecSa => "SAI_OBJECT_TYPE_MACSEC_SA",
            Self::SystemPort => "SAI_OBJECT_TYPE_SYSTEM_PORT",
            Self::FineGrainedHashField => "SAI_OBJECT_TYPE_FINE_GRAINED_HASH_FIELD",
            Self::SwitchTunnel => "SAI_OBJECT_TYPE_SWITCH_TUNNEL",
            Self::MySidEntry => "SAI_OBJECT_TYPE_MY_SID_ENTRY",
            Self::MyMac => "SAI_OBJECT_TYPE_MY_MAC",
            Self::NextHopGroupMap => "SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MAP",
            Self::Ipsec => "SAI_OBJECT_TYPE_IPSEC",
            Self::IpsecPort => "SAI_OBJECT_TYPE_IPSEC_PORT",
            Self::IpsecSa => "SAI_OBJECT_TYPE_IPSEC_SA",
            Self::GenericProgrammable => "SAI_OBJECT_TYPE_GENERIC_PROGRAMMABLE",
            Self::ArsProfile => "SAI_OBJECT_TYPE_ARS_PROFILE",
            Self::Ars => "SAI_OBJECT_TYPE_ARS",
            Self::AclTableChainGroup => "SAI_OBJECT_TYPE_ACL_TABLE_CHAIN_GROUP",
            Self::TwampSession => "SAI_OBJECT_TYPE_TWAMP_SESSION",
            Self::TamCounterSubscription => "SAI_OBJECT_TYPE_TAM_COUNTER_SUBSCRIPTION",
            Self::PoeDevice => "SAI_OBJECT_TYPE_POE_DEVICE",
            Self::PoePse => "SAI_OBJECT_TYPE_POE_PSE",
            Self::PoePort => "SAI_OBJECT_TYPE_POE_PORT",
            Self::IcmpEchoSession => "SAI_OBJECT_TYPE_ICMP_ECHO_SESSION",
            Self::PrefixCompressionTable => "SAI_OBJECT_TYPE_PREFIX_COMPRESSION_TABLE",
            Self::PrefixCompressionEntry => "SAI_OBJECT_TYPE_PREFIX_COMPRESSION_ENTRY",
            Self::SynceClock => "SAI_OBJECT_TYPE_SYNCE_CLOCK",
            Self::Max => "SAI_OBJECT_TYPE_MAX",
            Self::CustomRangeBase => "SAI_OBJECT_TYPE_CUSTOM_RANGE_BASE",
            Self::ExtensionsRangeBase => "SAI_OBJECT_TYPE_EXTENSIONS_RANGE_BASE",
        }
    }
}

impl From<SaiObjectType> for u32 {
    fn from(obj_type: SaiObjectType) -> Self {
        obj_type.to_u32()
    }
}

impl TryFrom<u32> for SaiObjectType {
    type Error = ();

    fn try_from(value: u32) -> Result<Self, Self::Error> {
        Self::from_u32(value).ok_or(())
    }
}

impl fmt::Display for SaiObjectType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.to_c_name())
    }
}

impl FromStr for SaiObjectType {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "SAI_OBJECT_TYPE_NULL" => Ok(Self::Null),
            "SAI_OBJECT_TYPE_PORT" => Ok(Self::Port),
            "SAI_OBJECT_TYPE_LAG" => Ok(Self::Lag),
            "SAI_OBJECT_TYPE_VIRTUAL_ROUTER" => Ok(Self::VirtualRouter),
            "SAI_OBJECT_TYPE_NEXT_HOP" => Ok(Self::NextHop),
            "SAI_OBJECT_TYPE_NEXT_HOP_GROUP" => Ok(Self::NextHopGroup),
            "SAI_OBJECT_TYPE_ROUTER_INTERFACE" => Ok(Self::RouterInterface),
            "SAI_OBJECT_TYPE_ACL_TABLE" => Ok(Self::AclTable),
            "SAI_OBJECT_TYPE_ACL_ENTRY" => Ok(Self::AclEntry),
            "SAI_OBJECT_TYPE_ACL_COUNTER" => Ok(Self::AclCounter),
            "SAI_OBJECT_TYPE_ACL_RANGE" => Ok(Self::AclRange),
            "SAI_OBJECT_TYPE_ACL_TABLE_GROUP" => Ok(Self::AclTableGroup),
            "SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER" => Ok(Self::AclTableGroupMember),
            "SAI_OBJECT_TYPE_HOSTIF" => Ok(Self::Hostif),
            "SAI_OBJECT_TYPE_MIRROR_SESSION" => Ok(Self::MirrorSession),
            "SAI_OBJECT_TYPE_SAMPLEPACKET" => Ok(Self::Samplepacket),
            "SAI_OBJECT_TYPE_STP" => Ok(Self::Stp),
            "SAI_OBJECT_TYPE_HOSTIF_TRAP_GROUP" => Ok(Self::HostifTrapGroup),
            "SAI_OBJECT_TYPE_POLICER" => Ok(Self::Policer),
            "SAI_OBJECT_TYPE_WRED" => Ok(Self::Wred),
            "SAI_OBJECT_TYPE_QOS_MAP" => Ok(Self::QosMap),
            "SAI_OBJECT_TYPE_QUEUE" => Ok(Self::Queue),
            "SAI_OBJECT_TYPE_SCHEDULER" => Ok(Self::Scheduler),
            "SAI_OBJECT_TYPE_SCHEDULER_GROUP" => Ok(Self::SchedulerGroup),
            "SAI_OBJECT_TYPE_BUFFER_POOL" => Ok(Self::BufferPool),
            "SAI_OBJECT_TYPE_BUFFER_PROFILE" => Ok(Self::BufferProfile),
            "SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP" => Ok(Self::IngressPriorityGroup),
            "SAI_OBJECT_TYPE_LAG_MEMBER" => Ok(Self::LagMember),
            "SAI_OBJECT_TYPE_HASH" => Ok(Self::Hash),
            "SAI_OBJECT_TYPE_UDF" => Ok(Self::Udf),
            "SAI_OBJECT_TYPE_UDF_MATCH" => Ok(Self::UdfMatch),
            "SAI_OBJECT_TYPE_UDF_GROUP" => Ok(Self::UdfGroup),
            "SAI_OBJECT_TYPE_FDB_ENTRY" => Ok(Self::FdbEntry),
            "SAI_OBJECT_TYPE_SWITCH" => Ok(Self::Switch),
            "SAI_OBJECT_TYPE_HOSTIF_TRAP" => Ok(Self::HostifTrap),
            "SAI_OBJECT_TYPE_HOSTIF_TABLE_ENTRY" => Ok(Self::HostifTableEntry),
            "SAI_OBJECT_TYPE_NEIGHBOR_ENTRY" => Ok(Self::NeighborEntry),
            "SAI_OBJECT_TYPE_ROUTE_ENTRY" => Ok(Self::RouteEntry),
            "SAI_OBJECT_TYPE_VLAN" => Ok(Self::Vlan),
            "SAI_OBJECT_TYPE_VLAN_MEMBER" => Ok(Self::VlanMember),
            "SAI_OBJECT_TYPE_HOSTIF_PACKET" => Ok(Self::HostifPacket),
            "SAI_OBJECT_TYPE_TUNNEL_MAP" => Ok(Self::TunnelMap),
            "SAI_OBJECT_TYPE_TUNNEL" => Ok(Self::Tunnel),
            "SAI_OBJECT_TYPE_TUNNEL_TERM_TABLE_ENTRY" => Ok(Self::TunnelTermTableEntry),
            "SAI_OBJECT_TYPE_FDB_FLUSH" => Ok(Self::FdbFlush),
            "SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER" => Ok(Self::NextHopGroupMember),
            "SAI_OBJECT_TYPE_STP_PORT" => Ok(Self::StpPort),
            "SAI_OBJECT_TYPE_RPF_GROUP" => Ok(Self::RpfGroup),
            "SAI_OBJECT_TYPE_RPF_GROUP_MEMBER" => Ok(Self::RpfGroupMember),
            "SAI_OBJECT_TYPE_L2MC_GROUP" => Ok(Self::L2mcGroup),
            "SAI_OBJECT_TYPE_L2MC_GROUP_MEMBER" => Ok(Self::L2mcGroupMember),
            "SAI_OBJECT_TYPE_IPMC_GROUP" => Ok(Self::IpmcGroup),
            "SAI_OBJECT_TYPE_IPMC_GROUP_MEMBER" => Ok(Self::IpmcGroupMember),
            "SAI_OBJECT_TYPE_L2MC_ENTRY" => Ok(Self::L2mcEntry),
            "SAI_OBJECT_TYPE_IPMC_ENTRY" => Ok(Self::IpmcEntry),
            "SAI_OBJECT_TYPE_MCAST_FDB_ENTRY" => Ok(Self::McastFdbEntry),
            "SAI_OBJECT_TYPE_HOSTIF_USER_DEFINED_TRAP" => Ok(Self::HostifUserDefinedTrap),
            "SAI_OBJECT_TYPE_BRIDGE" => Ok(Self::Bridge),
            "SAI_OBJECT_TYPE_BRIDGE_PORT" => Ok(Self::BridgePort),
            "SAI_OBJECT_TYPE_TUNNEL_MAP_ENTRY" => Ok(Self::TunnelMapEntry),
            "SAI_OBJECT_TYPE_TAM" => Ok(Self::Tam),
            "SAI_OBJECT_TYPE_SRV6_SIDLIST" => Ok(Self::Srv6Sidlist),
            "SAI_OBJECT_TYPE_PORT_POOL" => Ok(Self::PortPool),
            "SAI_OBJECT_TYPE_INSEG_ENTRY" => Ok(Self::InsegEntry),
            "SAI_OBJECT_TYPE_DTEL" => Ok(Self::Dtel),
            "SAI_OBJECT_TYPE_DTEL_QUEUE_REPORT" => Ok(Self::DtelQueueReport),
            "SAI_OBJECT_TYPE_DTEL_INT_SESSION" => Ok(Self::DtelIntSession),
            "SAI_OBJECT_TYPE_DTEL_REPORT_SESSION" => Ok(Self::DtelReportSession),
            "SAI_OBJECT_TYPE_DTEL_EVENT" => Ok(Self::DtelEvent),
            "SAI_OBJECT_TYPE_BFD_SESSION" => Ok(Self::BfdSession),
            "SAI_OBJECT_TYPE_ISOLATION_GROUP" => Ok(Self::IsolationGroup),
            "SAI_OBJECT_TYPE_ISOLATION_GROUP_MEMBER" => Ok(Self::IsolationGroupMember),
            "SAI_OBJECT_TYPE_TAM_MATH_FUNC" => Ok(Self::TamMathFunc),
            "SAI_OBJECT_TYPE_TAM_REPORT" => Ok(Self::TamReport),
            "SAI_OBJECT_TYPE_TAM_EVENT_THRESHOLD" => Ok(Self::TamEventThreshold),
            "SAI_OBJECT_TYPE_TAM_TEL_TYPE" => Ok(Self::TamTelType),
            "SAI_OBJECT_TYPE_TAM_TRANSPORT" => Ok(Self::TamTransport),
            "SAI_OBJECT_TYPE_TAM_TELEMETRY" => Ok(Self::TamTelemetry),
            "SAI_OBJECT_TYPE_TAM_COLLECTOR" => Ok(Self::TamCollector),
            "SAI_OBJECT_TYPE_TAM_EVENT_ACTION" => Ok(Self::TamEventAction),
            "SAI_OBJECT_TYPE_TAM_EVENT" => Ok(Self::TamEvent),
            "SAI_OBJECT_TYPE_NAT_ZONE_COUNTER" => Ok(Self::NatZoneCounter),
            "SAI_OBJECT_TYPE_NAT_ENTRY" => Ok(Self::NatEntry),
            "SAI_OBJECT_TYPE_TAM_INT" => Ok(Self::TamInt),
            "SAI_OBJECT_TYPE_COUNTER" => Ok(Self::Counter),
            "SAI_OBJECT_TYPE_DEBUG_COUNTER" => Ok(Self::DebugCounter),
            "SAI_OBJECT_TYPE_PORT_CONNECTOR" => Ok(Self::PortConnector),
            "SAI_OBJECT_TYPE_PORT_SERDES" => Ok(Self::PortSerdes),
            "SAI_OBJECT_TYPE_MACSEC" => Ok(Self::Macsec),
            "SAI_OBJECT_TYPE_MACSEC_PORT" => Ok(Self::MacsecPort),
            "SAI_OBJECT_TYPE_MACSEC_FLOW" => Ok(Self::MacsecFlow),
            "SAI_OBJECT_TYPE_MACSEC_SC" => Ok(Self::MacsecSc),
            "SAI_OBJECT_TYPE_MACSEC_SA" => Ok(Self::MacsecSa),
            "SAI_OBJECT_TYPE_SYSTEM_PORT" => Ok(Self::SystemPort),
            "SAI_OBJECT_TYPE_FINE_GRAINED_HASH_FIELD" => Ok(Self::FineGrainedHashField),
            "SAI_OBJECT_TYPE_SWITCH_TUNNEL" => Ok(Self::SwitchTunnel),
            "SAI_OBJECT_TYPE_MY_SID_ENTRY" => Ok(Self::MySidEntry),
            "SAI_OBJECT_TYPE_MY_MAC" => Ok(Self::MyMac),
            "SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MAP" => Ok(Self::NextHopGroupMap),
            "SAI_OBJECT_TYPE_IPSEC" => Ok(Self::Ipsec),
            "SAI_OBJECT_TYPE_IPSEC_PORT" => Ok(Self::IpsecPort),
            "SAI_OBJECT_TYPE_IPSEC_SA" => Ok(Self::IpsecSa),
            "SAI_OBJECT_TYPE_GENERIC_PROGRAMMABLE" => Ok(Self::GenericProgrammable),
            "SAI_OBJECT_TYPE_ARS_PROFILE" => Ok(Self::ArsProfile),
            "SAI_OBJECT_TYPE_ARS" => Ok(Self::Ars),
            "SAI_OBJECT_TYPE_ACL_TABLE_CHAIN_GROUP" => Ok(Self::AclTableChainGroup),
            "SAI_OBJECT_TYPE_TWAMP_SESSION" => Ok(Self::TwampSession),
            "SAI_OBJECT_TYPE_TAM_COUNTER_SUBSCRIPTION" => Ok(Self::TamCounterSubscription),
            "SAI_OBJECT_TYPE_POE_DEVICE" => Ok(Self::PoeDevice),
            "SAI_OBJECT_TYPE_POE_PSE" => Ok(Self::PoePse),
            "SAI_OBJECT_TYPE_POE_PORT" => Ok(Self::PoePort),
            "SAI_OBJECT_TYPE_ICMP_ECHO_SESSION" => Ok(Self::IcmpEchoSession),
            "SAI_OBJECT_TYPE_PREFIX_COMPRESSION_TABLE" => Ok(Self::PrefixCompressionTable),
            "SAI_OBJECT_TYPE_PREFIX_COMPRESSION_ENTRY" => Ok(Self::PrefixCompressionEntry),
            "SAI_OBJECT_TYPE_SYNCE_CLOCK" => Ok(Self::SynceClock),
            "SAI_OBJECT_TYPE_MAX" => Ok(Self::Max),
            "SAI_OBJECT_TYPE_CUSTOM_RANGE_BASE" => Ok(Self::CustomRangeBase),
            "SAI_OBJECT_TYPE_EXTENSIONS_RANGE_BASE" => Ok(Self::ExtensionsRangeBase),
            _ => Err(()),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_int_conversion() {
        assert_eq!(SaiObjectType::Null.to_u32(), 0);
        assert_eq!(SaiObjectType::Port.to_u32(), 1);
        assert_eq!(SaiObjectType::from_u32(0), Some(SaiObjectType::Null));
        assert_eq!(SaiObjectType::from_u32(1), Some(SaiObjectType::Port));
        assert_eq!(SaiObjectType::from_u32(u32::MAX), None);
    }

    #[test]
    fn test_string_conversion() {
        assert_eq!(SaiObjectType::Null.to_c_name(), "SAI_OBJECT_TYPE_NULL");
        assert_eq!(SaiObjectType::Port.to_c_name(), "SAI_OBJECT_TYPE_PORT");
        assert_eq!(
            "SAI_OBJECT_TYPE_NULL".parse::<SaiObjectType>(),
            Ok(SaiObjectType::Null)
        );
        assert_eq!(
            "SAI_OBJECT_TYPE_PORT".parse::<SaiObjectType>(),
            Ok(SaiObjectType::Port)
        );
        assert!("INVALID".parse::<SaiObjectType>().is_err());
    }

    #[test]
    fn test_display() {
        assert_eq!(format!("{}", SaiObjectType::Null), "SAI_OBJECT_TYPE_NULL");
        assert_eq!(format!("{}", SaiObjectType::Port), "SAI_OBJECT_TYPE_PORT");
    }
}
